import { EllipsoidGraphics } from "cesium";
import { BaseEntity } from "./BaseEntity";
import * as Cesium from "cesium";
import type { RadarEntityOptions } from "../interfaces/entity";
import { CallbackProperty } from "cesium";
import { Cartesian3 } from "cesium";
import type { Entity } from "cesium";

/**
 * 雷达实体类，用于创建和管理雷达扫描区域及目标追踪功能
 *
 * 使用案例演示
 *
 * @example
 * // 1. 创建Viewer
 * const viewer = new Cesium.Viewer('cesiumContainer');
 *
 * // 2. 创建雷达实体
 * const radar = new RadarEntity({
 *   position: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 100),
 *   Model: {
 *     src: '/models/radar.glb',
 *     minimumPixelSize: 128
 *   }
 * });
 * viewer.entities.add(radar.entity);
 *
 * // 3. 创建目标实体
 * const target = viewer.entities.add({
 *   id: 'target-entity',
 *   position: Cesium.Cartesian3.fromDegrees(116.41, 39.91, 100),
 *   model: {
 *     uri: '/models/target.glb',
 *     minimumPixelSize: 64
 *   }
 * });
 *
 * // 4. 设置雷达追踪目标
 * radar.setTrackTarget('target-entity');
 *
 * // 5. 动画目标移动
 * let angle = 0;
 * setInterval(() => {
 *   angle += 0.01;
 *   target.position = Cesium.Cartesian3.fromDegrees(
 *     116.41 + Math.cos(angle) * 0.1,
 *     39.91 + Math.sin(angle) * 0.1,
 *     100
 *   );
 * }, 50);
 */
export class RadarEntity extends BaseEntity {
  /** 雷达配置选项 */
  private _options: RadarEntityOptions;

  /**
   * 构造函数
   * @param options 雷达配置选项
   */
  constructor(options: RadarEntityOptions) {
    super(options);
    this._options = options;
    this.setAppearance();
    this.setScanArea();
  }

  /**
   * 设置雷达外观
   */
  protected setAppearance(): void {
    this._entity.ellipsoid = new EllipsoidGraphics();
    this.setModel();
  }

  /**
   * 设置雷达模型
   *
   * @example
   * // 动态更新模型
   * radar.setModel({
   *   src: '/models/new_radar.glb',
   *   minimumPixelSize: 256
   * });
   */
  private setModel() {
    if (!this._options.Model) return;
    const { src, minimumPixelSize } = this._options.Model;

    this._entity.model = new Cesium.ModelGraphics({
      uri: src,
      minimumPixelSize,
    });
  }

  /**
   * 设置雷达扫描区域
   *
   * @example
   * // 自定义扫描区域
   * radar.setScanArea({
   *   radii: new Cesium.Cartesian3(300000, 300000, 300000),
   *   material: Cesium.Color.BLUE.withAlpha(0.3)
   * });
   */
  private setScanArea(): void {
    this._entity.ellipsoid = new EllipsoidGraphics({
      radii: new Cesium.Cartesian3(500000, 500000, 500000),
      innerRadii: new Cesium.Cartesian3(1, 1, 1),
      minimumClock: Cesium.Math.toRadians(180 - 45),
      maximumClock: Cesium.Math.toRadians(180 + 45),
      minimumCone: Cesium.Math.toRadians(90 - 20),
      maximumCone: Cesium.Math.toRadians(90 + 20),
      material: Cesium.Color.GREEN.withAlpha(0.4),
      fill: true,
      outline: true,
      outlineColor: Cesium.Color.GREEN,
      outlineWidth: 1.0,
      slicePartitions: 32,
      stackPartitions: 32,
      subdivisions: 12,
      shadows: Cesium.ShadowMode.ENABLED,
      heightReference: Cesium.HeightReference.NONE,
    });
  }

  /**
   * 设置目标追踪
   * @param id 目标实体ID
   *
   * @example
   * // 追踪目标
   * radar.setTrackTarget('target-entity-id');
   *
   * // 停止追踪
   * radar.setTrackTarget(null);
   */
  setTrackTarget(id: string | null) {
    if (!id) {
      // 清除追踪状态
      this._entity.orientation = undefined;
      return;
    }

    const target = this.entityManager?.getById(id);
    const targetEntity = target?.entity;
    const currentEntity = this._entity;

    if (!target || !targetEntity) return;
    this.faceAtoB(currentEntity, targetEntity);
    this.setMaterial(targetEntity, currentEntity);
  }

  /**
   * 使实体A朝向实体B
   * @param A 需要旋转的实体
   * @param B 目标实体
   */
  private faceAtoB(A: Cesium.Entity, B: Cesium.Entity) {
    let currentQuaternion = Cesium.Quaternion.IDENTITY;

    A.orientation = new Cesium.CallbackProperty((t) => {
      const positionA = A.position!.getValue(t);
      const positionB = B.position!.getValue(t);
      if (!positionA || !positionB || !t) return currentQuaternion;

      const dis = Cesium.Cartesian3.distance(positionA, positionB);
      const maxDistance = A?.ellipsoid?.radii?.getValue(t).x || 0;

      let targetQuaternion;
      if (dis <= maxDistance) {
        const worldDirection = Cesium.Cartesian3.subtract(
          positionA,
          positionB,
          new Cesium.Cartesian3()
        );
        Cesium.Cartesian3.normalize(worldDirection, worldDirection);

        const enuMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
          positionA,
          Cesium.Ellipsoid.WGS84,
          new Cesium.Matrix4()
        );
        const enuDirection = Cesium.Matrix4.multiplyByPointAsVector(
          Cesium.Matrix4.inverse(enuMatrix, new Cesium.Matrix4()),
          worldDirection,
          new Cesium.Cartesian3()
        );

        const { x: east, y: north, z: up } = enuDirection;
        const heading = Math.atan2(east, north);
        const pitch = -Math.asin(up);
        const roll = 0;

        const hpr = new Cesium.HeadingPitchRoll(
          heading + (Math.PI / 2) * 3,
          pitch,
          roll
        );
        targetQuaternion = Cesium.Transforms.headingPitchRollQuaternion(
          positionA,
          hpr
        );
      } else {
        const initialHPR = new Cesium.HeadingPitchRoll(0, 0, 0);
        targetQuaternion = Cesium.Transforms.headingPitchRollQuaternion(
          positionA,
          initialHPR
        );
      }

      const lerpFactor = 0.1;
      currentQuaternion = Cesium.Quaternion.lerp(
        currentQuaternion,
        targetQuaternion,
        lerpFactor,
        new Cesium.Quaternion()
      );

      return currentQuaternion;
    }, false);
  }

  /**
   * 设置目标材质
   * @param targetEntity 目标实体
   * @param currentEntity 当前雷达实体
   */
  private setMaterial(targetEntity: Entity, currentEntity: Entity) {
    const color = this.colorCallbackProperty(targetEntity, currentEntity);
    targetEntity.model!.color = color;
    currentEntity.ellipsoid!.material = new Cesium.ColorMaterialProperty(color);
    currentEntity.ellipsoid!.outlineColor = color;
  }

  /**
   * 创建颜色回调属性
   * @param targetEntity 目标实体
   * @param currentEntity 当前雷达实体
   * @returns 颜色回调属性
   */
  private colorCallbackProperty(targetEntity: Entity, currentEntity: Entity) {
    let currentColor = Cesium.Color.GREEN.withAlpha(0.2);

    return new CallbackProperty((t) => {
      if (!currentEntity || !targetEntity) return currentColor;
      const pos1 = targetEntity?.position?.getValue(t);
      const pos2 = currentEntity?.position?.getValue(t);
      const s = currentEntity?.ellipsoid?.radii?.getValue(t).x;

      if (pos1 && pos2) {
        const dis = Cartesian3.distance(pos1, pos2);
        currentColor =
          dis > s
            ? Cesium.Color.GREEN.withAlpha(0.2)
            : Cesium.Color.RED.withAlpha(0.2);
      }

      return currentColor;
    }, false);
  }
}

